import 'dart:math';

class GPS {
  static const a = 6378245.0;
  static const ee = 0.00669342162296594323;
  static const xpi = 3.14159265358979324 * 3000.0 / 180.0;
//世界大地坐标转为百度坐标
  static List<double> wgs2bd(num lat, num lon) {
    var wgs2gcjR = wgs2gcj(lat, lon);
    var gcj2bdR = gcj2bd(wgs2gcjR[0], wgs2gcjR[1]);
    return gcj2bdR;
  }

  static List<double> gcj2bd(num lat, num lon) {
    var x = lon, y = lat;
    var z = sqrt(x * x + y * y) + 0.00002 * sin(y * xpi);
    var theta = atan2(y, x) + 0.000003 * cos(x * xpi);
    var bdLon = z * cos(theta) + 0.0065;
    var bdLat = z * sin(theta) + 0.006;
    List<double> result = [];
    result.add(bdLat);
    result.add(bdLon);
    return result;
  }

  static List<double> bd2gcj(num lat, num lon) {
    var x = lon - 0.0065, y = lat - 0.006;
    var z = sqrt(x * x + y * y) - 0.00002 * sin(y * xpi);
    var theta = atan2(y, x) - 0.000003 * cos(x * xpi);
    var ggLon = z * cos(theta);
    var ggLat = z * sin(theta);
    List<double> result = [];
    result.add(ggLat);
    result.add(ggLon);
    return result;
  }

  static List<double> wgs2gcj(num lat, num lon) {
    var dLat = GPS().transformLat(lon - 105.0, lat - 35.0);
    var dLon = GPS().transformLon(lon - 105.0, lat - 35.0);
    var radLat = lat / 180.0 * pi;
    var magic = sin(radLat);
    magic = 1 - ee * magic * magic;
    var sqrtMagic = sqrt(magic);
    dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
    dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * pi);
    var mgLat = lat + dLat;
    var mgLon = lon + dLon;
    List<double> result = [];
    result.add(mgLat as double);
    result.add(mgLon as double);
    return result;
  }

  List<double> bd2wgs(num bdLat, num bdLon) {
    var gcj02 = bd2gcj(bdLat, bdLon);
    var map84 = gcj2wgs(gcj02[0], gcj02[1]);
    return map84;
  }

  List<double> gcj2wgs(num lat, num lon) {
    var gps = wgs2gcj(lat, lon);
    var lontitude = lon * 2 - gps[1];
    var latitude = lat * 2 - gps[0];
    return [latitude, lontitude];
  }

  transformLat(num lat, num lon) {
    var ret = -100.0 +
        2.0 * lat +
        3.0 * lon +
        0.2 * lon * lon +
        0.1 * lat * lon +
        0.2 * sqrt(abs(lat));
    ret +=
        (20.0 * sin(6.0 * lat * pi) + 20.0 * sin(2.0 * lat * pi)) * 2.0 / 3.0;
    ret += (20.0 * sin(lon * pi) + 40.0 * sin(lon / 3.0 * pi)) * 2.0 / 3.0;
    ret +=
        (160.0 * sin(lon / 12.0 * pi) + 320 * sin(lon * pi / 30.0)) * 2.0 / 3.0;
    return ret;
  }

  transformLon(num lat, num lon) {
    var ret = 300.0 +
        lat +
        2.0 * lon +
        0.1 * lat * lat +
        0.1 * lat * lon +
        0.1 * sqrt(abs(lat));
    ret +=
        (20.0 * sin(6.0 * lat * pi) + 20.0 * sin(2.0 * lat * pi)) * 2.0 / 3.0;
    ret += (20.0 * sin(lat * pi) + 40.0 * sin(lat / 3.0 * pi)) * 2.0 / 3.0;
    ret += (150.0 * sin(lat / 12.0 * pi) + 300.0 * sin(lat / 30.0 * pi)) *
        2.0 /
        3.0;
    return ret;
  }

  num abs(num x) {
    if (x >= 0) {
      return x;
    } else {
      return -x;
    }
  }
}
